﻿using Furion.CMS.Application;
using Furion.CMS.Application.Dto;
using Furion.CMS.Core;
using Furion.CMS.Domain;
using Furion.DependencyInjection;
using Furion.FriendlyException;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;

namespace Furion.CMS.Web.Core.FileUpload
{
    /// <summary>
    /// 阿里云OSS文件上传
    /// </summary>
    [Injection(Named = nameof(StorageMode.AliyunOSS))]
    public class AliyunOSSFileUpload : IFileUploadProvider, ITransient
    {
        private readonly SiteSettingAppService siteSetting;

        /// <summary>
        /// 站点设置信息
        /// </summary>
        public SiteSetting Site { get => siteSetting.GetTenantSettings(); }

        /// <summary>
        /// 存储库参数
        /// </summary>
        public ObjectStorageParams Storage { get => Site?.ObjectStorageParam; }

        public AliyunOSSFileUpload(SiteSettingAppService siteSetting)
        {
            this.siteSetting = siteSetting;
        }

        public string CallbackHandler(ICloudCallbackModel callbackParams)
        {
            if (callbackParams is AliyunOSSCallbackModel aliyunOSSCallback)
            {
                return aliyunOSSCallback.filename;
            }
            throw Oops.Oh("参数错误");
        }

        public UploadConfigre GetConfigre()
        {
            var expireDateTime = DateTime.Now.AddMinutes(10); // 设置单次上传凭据的有效时间为10分钟
            var host = Storage.Url;
            var accessKeyID = Storage.KeyId;
            var accessKeySecret = Storage.KeySecret;

            var policyObj = new Dictionary<string, object>() {
                    {"expiration",expireDateTime.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss.fff'Z'",CultureInfo.CurrentCulture) },
                    {"conditions",new object[]{
                        new object[] { "content-length-range", 0, 1048576000 },
                    } }
                };
            var policyStr = Newtonsoft.Json.JsonConvert.SerializeObject(policyObj);
            var policy = Convert.ToBase64String(Encoding.UTF8.GetBytes(policyStr));
            var signature = policy.ToBase64HMAC(accessKeySecret);
            var callbackHost = Site.HostUrl;

#if DEBUG
            // debug模式下,使用mock来接收回调并返回消息体
            callbackHost = "https://www.fastmock.site/mock/b15e2648340c7c065b87828d6e1d893d/furion-cms";
#endif
            var callbackUrl = $"{callbackHost}/api/file-center/cloud-callback/aliyun";

            var callbackParam = new
            {
                callbackUrl,
                callbackBodyType = "application/x-www-form-urlencoded",
                callbackBody = "filename=" + host + "/${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}"
            };
            var callback = Convert.ToBase64String(Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(callbackParam)));

            return new UploadConfigre
            {
                Host = host,
                ExtraData = new Dictionary<string, object>()
                {
                    {"OSSAccessKeyId", accessKeyID },
                    {"policy", policy },
                    {"Signature", signature },
                    {"success_action_status", 200 },
                    {"callback", callback },
                }
            };
        }
    }
}
